<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Cell Visualization</title>
  <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
  <script src='https://api.mapbox.com/mapbox-gl-js/v0.42.0/mapbox-gl.js'></script>
  <script src="http://d3js.org/d3.v3.min.js"></script>
  <script src="//d3js.org/topojson.v1.min.js"></script>
  <script src="heatmap.js"></script>
  <link href='https://api.mapbox.com/mapbox-gl-js/v0.42.0/mapbox-gl.css' rel='stylesheet' />
  <style>
	.div{
		position:absolute;
		z-index:1;
	}
	.div2{
		position:absolute;
		width:100%; height:100%;
		opacity:1;
		filter: alpha(opacity=100);
		z-index:2;
	}
    body { margin:0; padding:0; }
    #map { position:absolute; top:0; bottom:0; width:100%; height:100%;}
    #menu {
        background: #fff;
        position: absolute;
        top: 10px;
        right: 10px;
        border-radius: 3px;
        width: 120px;
        border: 1px solid rgba(0,0,0,0.4);
        font-family: 'Open Sans', sans-serif;
        z-index:3;
    }
    svg {
      position: absolute;
      width: 100%;
      height: 100%;
    }
    #menu a {
        font-size: 13px;
        color: #404040;
        display: block;
        margin: 0;
        padding: 0;
        padding: 10px;
        text-decoration: none;
        border-bottom: 1px solid rgba(0,0,0,0.25);
        text-align: center;
    }

    #menu a:last-child {
        border: none;
    }

    #menu a:hover {
        background-color: #f8f8f8;
        color: #404040;
    }

    #menu a.active {
        background-color: #3887be;
        color: #ffffff;
    }

    #menu a.active:hover {
        background: #3074a4;
    }
  </style>
</head>

<body>
  <nav id="menu"></nav>
  <div id='map' class="div"></div>
  <div id='heat' class="div2"></div>
  <script>
    mapboxgl.accessToken = 'pk.eyJ1IjoiZXNvbmpvaG4iLCJhIjoiY2piYzhnenZvMWdxdTMybXI3NGhmMXF6YyJ9.ue_phfqDiwJrzxmcXfYFjA';
    var map = new mapboxgl.Map({
      container: 'map',
      style: 'mapbox://styles/mapbox/light-v9',
      //center: [121.5572, 38.99029],  // starting position [lng, lat]
      center: [122, 39],
      //center:[-121.687, 37.8754],
      zoom: 8,             // starting zoom
    });
    //var color = Array();
    //color.push('#F7455D');
    //color.push('#33C9EB');
    
    //使用d3的color生成器
    var color = d3.scale.category20();

	var trajectory1 = [
                [-122.4833858013153, 37.829607404976734],
                [-122.4830961227417, 37.82932776098012],
                [-122.4830746650696, 37.82932776098012],
                [-122.48218417167662, 37.82889558180985],
                [-122.48218417167662, 37.82890193740421],
                [-122.48221099376678, 37.82868372835086],
                [-122.4822163581848, 37.82868372835086],
                [-122.48205006122589, 37.82801003030873]
	         ];
    var trajectory2 = [
                [-122.48393028974533, 37.829471820141016],
                [-122.48395174741744, 37.82940826466351],
                [-122.48395174741744, 37.829412501697064],
                [-122.48423874378203, 37.829357420242125],
                [-122.48422533273697, 37.829361657278575],
                [-122.48459815979002, 37.8293425906126],
                [-122.48458743095398, 37.8293447091313],
                [-122.4847564101219, 37.82932776098012],
                [-122.48474299907684, 37.829331998018276],
                [-122.4849334359169, 37.829298101706186],
                [-122.48492807149889, 37.82930022022615],
                [-122.48509705066681, 37.82920488676767],
                [-122.48509168624878, 37.82920912381288],
                [-122.48520433902739, 37.82905870855876],
                [-122.48519897460936, 37.82905870855876],
                [-122.4854403734207, 37.828594749716714],
                [-122.48543500900269, 37.82860534241688],
                [-122.48571664094925, 37.82808206121068],
                [-122.48570591211319, 37.82809689109353],
                [-122.4858346581459, 37.82797189627337],
                [-122.48582661151886, 37.82797825194729],
                [-122.4859634041786, 37.82788503534145],
                [-122.48595803976059, 37.82788927246246],
                [-122.48605459928514, 37.82786596829394]
	         ];
	    
	    var tr = new Array();
	    //JS-array的两种添加元素方法
	    //tr[0] = trajectory1;
	    //tr[1] = trajectory2;
	    tr.push(trajectory1);
	    tr.push(trajectory2);

	    // 获取d3的projector
	    function getD3Projector() {
	      var center = map.getCenter();
	      var zoom = map.getZoom();
	      // 512 is hardcoded tile size, might need to be 256 or changed to suit your map config
	      var scale = (512) * 0.5 / Math.PI * Math.pow(2, zoom);

	      var d3projection = d3.geo.mercator()
	        .center([center.lng, center.lat])
	        .translate([window.innerWidth/2, window.innerHeight/2])		//should accordance with mapbox size
	        .scale(scale);

	      return d3projection;
	    }

	map.on('load', function() {
	    //console.log("################# load");
	    map.addSource('earthquakes', {
	        "type": "geojson",
	        "data": "./earthquakes.geojson"
    	});
//-----------------------------------------------------

		//添加base节点

		/*
		//方法一：使用Mapbox的添加layer的方法，该方法在点较多的时候会特别卡顿
		d3.csv("BASE.csv",function(error,csvdata){  
		    if(error){  
		        console.log(error);  
		    }  

		    console.log(csvdata);
		    //console.log([parseFloat(csvdata[1].longitude), parseFloat(csvdata[1].latitude)]);

		    for(var i = 0; i < 300; i++)
		    {
		    	map.addLayer({
			        "id": csvdata[i].base_id,//"base"+(i*tr[0].length+j),
			        "type": "symbol",
			        "source": {
			            "type": "geojson",
			            "data": {
			                "type": "FeatureCollection",
			                "features": [{
			                    "type": "Feature",
			                    "geometry": {
			                        "type": "Point",
			                        "coordinates": [parseFloat(csvdata[i].longitude), parseFloat(csvdata[i].latitude)]
			                    },
			                    "properties": {
			                        "title": csvdata[i].base_id,
			                        "icon": "monument"
			                    }
			                }]
			            }
			        },
			        "layout": {
			            "icon-image": "{icon}-15",
			            "text-field": "{title}",
			            "text-font": ["Open Sans Semibold", "Arial Unicode MS Bold"],
			            "text-offset": [0, 0.6],
			            "text-anchor": "top",
			            "text-size": 10,
		        		'visibility':'visible'
			        }
		    	});
		    }
		});
		*/

		/*
		//方法二：使用Mapbox Studio上传文件生成url
	    map.addSource('mBaseTilesetSource', {
		    type: 'vector',
		    url: 'mapbox://esonjohn.cjbf0ugcj2rvx2xlltunxuu36-5wpxz'	//generated by https://www.mapbox.com/studio/tilesets/
		});
	    map.addLayer({
	        'id': 'baseLayer',
	        'type': 'circle',
	        'source': 'mBaseTilesetSource',
	        'source-layer':'BASE',
	        'paint': {
	            // make circles larger as the user zooms from z12 to z22
	            'circle-radius': {
	                'base': 1.75,
	                'stops': [[12, 2], [22, 180]]
	            },
	            // color circles by ethnicity, using data-driven styles
	            'circle-color': {
	                property: 'ethnicity',
	                type: 'categorical',
	                stops: [
	                    ['White', '#fbb03b'],
	                    ['Black', '#223b53'],
	                    ['Hispanic', '#e55e5e'],
	                    ['Asian', '#3bb2d0'],
	                    ['Other', '#ccc']]
	            }
	        }
	    });
	    */
		
		//方法三：使用D3获取mapbox的container,然后用d3作画 (fancy!!)
	    // Setup our svg layer that we can manipulate with d3
	    var container = map.getCanvasContainer();
	    var svg = d3.select(container).append("svg").attr("id", "svg");

	    // calculate the original d3 projection
	    //var d3Projection = getD3Projector();
	    //var path = d3.geo.path();

	    //var url = "http://enjalot.github.io/wwsd/data/UK/london_stations.topojson";
	    d3.csv("./BASE.csv", function(err, data) {
	      //var points = topojson.feature(data, data.objects.london_stations);
	      //console.log(data);
	      //console.log(data[0], getLL(data[0]), project(data[0]));
	      var dots = svg.selectAll("circle.dot")
	      				.data(data);


		//---------test:往svg里添加图形
		/*
		svg.append("rect")
			  .attr("id", "rect1")
		      .attr("x", d3Projection([122.5572,38.93029])[0])
		      .attr("y", d3Projection([122.5572,38.93029])[1])
		      .attr("rx", 4)
		      .attr("ry", 4)
		      .attr("class", "hour bordered")
		      .attr("width", 50)
		      .attr("height", 50)
		      .style("fill", "#00ffd9")
		      //.merge(cards)
		      .transition()
		      .duration(1000)
		      .attr({
		          cx: d3Projection([122.5572,38.93029])[0],	
		          cy: d3Projection([122.5572,38.93029])[1],
		       });

		svg.append("circle")
			  .attr("id", "circle2")
	      	  .classed("dot", true)
		      .attr("r", 1)
		      .style({
		        fill: "#ff0000",
		        "fill-opacity": 1,
		        stroke: "#ff0000",
		        "stroke-width": 1
		      })
		      .transition()
		      .duration(1000)
		      .attr("r", 10);
		*/
		//---------end-test

	      dots.enter()
	      	  .append("circle")
	      	  .classed("dot", true)
		      .attr("r", 1)
		      .style({
		        fill: "#0082a3",
		        "fill-opacity": 0.5,
		        stroke: "#004d60",
		        "stroke-width": 1
		      })
		      .transition()
		      .duration(1000)
		      .attr("r", 3);
	      
	      function renderBase() {
	      	//console.log("################# renderBase");
	        d3Projection = getD3Projector();
	        //path.projection(d3Projection);
	        
	        var cor = [function(d) { 
	            var x = d3Projection([d.longitude, d.latitude])[0];
	            return x
	          }, function(d) {
	            var y = d3Projection([d.longitude, d.latitude])[1];
	            return y
	          }];
	        //console.log(cor[0], cor[1]);
	        dots
	        .attr({
	          cx: cor[0],
	          cy: cor[1]
	        });

	        //--------------用于单独向svg里添加的图形的刷新----------------------
	        /*
	        svg.select("#rect1")
	          .attr({
	          cx: d3Projection([122.5572,38.93029])[0],	
	          cy: d3Projection([122.5572,38.93029])[1],
	          x: d3Projection([122.5572,38.93029])[0],
	          y: d3Projection([122.5572,38.93029])[1]
	        });

	        svg.select("#circle2")
	          .attr({
	          cx: d3Projection([122.5572,38.93029])[0],	
	          cy: d3Projection([122.5572,38.93029])[1],
	          x: d3Projection([122.5572,38.93029])[0],
	          y: d3Projection([122.5572,38.93029])[1]
	        });
	       */
	       //---------------------------------------------------------------
	      };

	      // re-render our visualization whenever the view changes
	      //map.on("viewreset", function() {
	        //renderBase();
	      //});
	      map.on("move", function() {
	        renderBase();
	      })

	      // render our initial visualization
	      renderBase();
	    });

//-----------------------------------------------------------

	    //添加轨迹
	    d3.csv("./trajectory.csv",function(error,csvdata){
		    if(error){  
		        console.log(error);
		    }

		    //console.log(csvdata);
		    //console.log([parseFloat(csvdata[1].longitude), parseFloat(csvdata[1].latitude)]);
		    var traj = Array();
		    for(var i = 0; i < csvdata.length; i++)
		    {
		    	traj.push([parseFloat(csvdata[i].longitude), parseFloat(csvdata[i].latitude)]);
		    }
		    //console.log(traj);

		    //添加轨迹图层
		    map.addLayer({
		        'id': 'trajLayer',
		        'type': 'line',
		        'source': {
		            'type': 'geojson',
		            'data': {
		                'type': 'FeatureCollection',
		                'features': [{
		                    'type': 'Feature',
		                    'properties': {
		                        'color': color(i),
		                    },
		                    'geometry': {
		                        'type': 'LineString',
		                        'coordinates': traj
		                    }
		                }]
		            }
		        },
		        // The identity function does not take a 'stops' property.
		        // Instead, the property value (in this case, 'color') on the source will be the direct output.
		        'paint': {
		            'line-width': 2,
		            'line-color': {
		                'type': 'identity',
		                'property': 'color'
		            }
		        },
		        'layout': {
		        	'visibility':'visible'
		        }
		    });
		});

//-----------------------------------------------------------
		
		//添加热力图图层
		/*
		//方法一：使用mapbox的图层api(因数据形式为geojson，不好按需产生？)
		map.addLayer({
	        "id": "earthquakes-heat",
	        "type": "heatmap",
	        "source": "earthquakes",
	        "maxzoom": 9,
	        "paint": {
	            //Increase the heatmap weight based on frequency and property magnitude
	            "heatmap-weight": {
	                "property": "mag",
	                "type": "exponential",
	                "stops": [
	                    [0, 0],
	                    [6, 1]
	                ]
	            },
	            //Increase the heatmap color weight weight by zoom level
	            //heatmap-ntensity is a multiplier on top of heatmap-weight
	            "heatmap-intensity": {
	                "stops": [
	                    [0, 1],
	                    [9, 3]
	                ]
	            },
	            //Color ramp for heatmap.  Domain is 0 (low) to 1 (high).
	            //Begin color ramp at 0-stop with a 0-transparancy color
	            //to create a blur-like effect.
	            "heatmap-color": [
	                "interpolate",
	                ["linear"],
	                ["heatmap-density"],
	                0, "rgba(33,102,172,0)",
	                0.2, "rgb(103,169,207)",
	                0.4, "rgb(209,229,240)",
	                0.6, "rgb(253,219,199)",
	                0.8, "rgb(239,138,98)",
	                1, "rgb(178,24,43)"
	            ],
	            //Adjust the heatmap radius by zoom level
	            "heatmap-radius": {
	                "stops": [
	                    [0, 2],
	                    [9, 20]
	                ]
	            },
	            //Transition from heatmap to circle layer by zoom level
	            "heatmap-opacity": {
	                "default": 1,
	                "stops": [
	                    [7, 1],
	                    [9, 0]
	                ]
	            },
	        }
    	}, 'waterway-label');

	    map.addLayer({
	        "id": "earthquakes-point",
	        "type": "circle",
	        "source": "earthquakes",
	        "minzoom": 7,
	        "paint": {
	            //Size circle raidus by earthquake magnitude and zoom level
	            "circle-radius": {
	                "property": "mag",
	                "type": "exponential",
	                "stops": [
	                    [{ zoom: 7, value: 1 }, 1],
	                    [{ zoom: 7, value: 6 }, 4],
	                    [{ zoom: 16, value: 1 }, 5],
	                    [{ zoom: 16, value: 6 }, 50],
	                ]
	            },
	            //Color circle by earthquake magnitude
	            "circle-color": {
	                "property": "mag",
	                "type": "exponential",
	                "stops": [
	                    [1, "rgba(33,102,172,0)"],
	                    [2, "rgb(103,169,207)"],
	                    [3, "rgb(209,229,240)"],
	                    [4, "rgb(253,219,199)"],
	                    [5, "rgb(239,138,98)"],
	                    [6, "rgb(178,24,43)"]
	                ]
	            },
	            "circle-stroke-color": "white",
	            "circle-stroke-width": 1,
	            //Transition from heatmap to circle layer by zoom level
	            "circle-opacity": {
	                "stops": [
	                    [7, 0],
	                    [8, 1]
	                ]
	            }
	        }
	    }, 'waterway-label');
    	*/

    	//方法二：使用heatmap.js
        //读入数据（随机产生数据用于测试）
		var origindata = [];
		var max = 0;
		var len = 200;
		while (len--) {
		    var val = Math.floor(Math.random()*100);
		    max = Math.max(max, val);
		    var prepoint = [Math.random()*1+121.5, Math.random()*1+38.5];

		    var point = {
		        x: prepoint[0],
		        y: prepoint[1],
		        value: val
		    };
		    origindata.push(point);
		}

		//重新渲染heatmap
		function renderHeat()
		{
			//删除原来的heatmap的div
			var box = document.getElementById("heat");  
			box.parentNode.removeChild(box);

			//添加新的heatmap的div
			d3.select("body")
			   .append("div")
			   .attr("id", "heat")
			   .attr("class", "div2");

	        //对点进行投影
			var points = [];
	        var projection_heat = getD3Projector();
	        for(var i = 0; i < 200; i++)
	        {
			    var cor = projection_heat([origindata[i].x, origindata[i].y]);
			    var point = {
			        x: cor[0],
			        y: cor[1],
			        value: val
		    	}
		    	points.push(point);
		    };
			var testData = {
			    max: max,
			    data: points
			};
	        //console.log(testData);

	        //建立热力图
	        var heatmapLayer = h337.create({
			    container: document.querySelector('#heat')	//map.getCanvasContainer()
			});

	        //导入数据
	        heatmapLayer.setData(testData);
		}

		//第一次载入时做一次渲染
		renderHeat();

//-----------------------------------------------------------------

		//设置图层visibility控制
		var toggleableLayerIds = ['trajectory', 'base' , 'heat'];

		for (var i = 0; i < toggleableLayerIds.length; i++) {

			var link = document.createElement('a');
			    link.href = '#';
			    link.className = 'active';
			    link.textContent = toggleableLayerIds[i];

		    link.onclick = function (e) 
		    {
			    if(this.text == "trajectory")	//对于轨迹，更改visibility属性
			    {
			        var clickedLayer = "trajLayer";
			        e.preventDefault();
			        e.stopPropagation();

			        var visibility = map.getLayoutProperty(clickedLayer, 'visibility');

			        if (this.className == 'active') {
			            map.setLayoutProperty(clickedLayer, 'visibility', 'none');
			            this.className = '';
			        } else {
			            map.setLayoutProperty(clickedLayer, 'visibility', 'visible');
			            this.className = 'active';
			        }
			    }else if(this.text == "base")	//对于基站，更改visibility属性
			    {
			    	if (this.className == '') {
			    		document.querySelector('svg').style.visibility="visible";
			            this.className = 'active';
			        } else {
			    		document.querySelector('svg').style.visibility="hidden";
			            this.className = '';
			        }
			    }else if(this.text == "heat")	//对于heat图层的visibility控制
			    {
			    	if (this.className == '') {
			    		renderHeat();
			            this.className = 'active';
			        } else {
			    		document.getElementById('heat').innerHTML = "";
			            this.className = '';
			        }
			    }
		    };

		    var layers = document.getElementById('menu');
		    layers.appendChild(link);
		}

	});
</script>
</body>
</html>